<template>
  <div v-loading="listLoading">
    <div v-if="showTitleWithText" :style="headerStyle" class="datatable-header">
      <div class="header-text">{{ title }}</div>
    </div>
    <el-table
      :data="list"
      :size="size"
      :width="width"
      :height="height"
      :max-height="maxHeight"
      :fit="fit"
      :stripe="stripe"
      :border="border"
      :row-key="rowKey"
      :show-header="showHeader"
      :show-summary="showSummary"
      :sum-text="sumText"
      :summary-method="summaryMethod"
      :row-class-name="rowClassName"
      :row-style="rowStyle"
      :cell-class-name="cellClassName"
      :cell-style="cellStyle"
      :header-row-class-name="headerRowClassName"
      :header-row-style="headerRowStyle"
      :header-cell-class-name="headerCellClassName"
      :header-cell-style="headerCellStyle"
      :highlight-current-row="highlightCurrentRow"
      :current-row-key="currentRowKey"
      :empty-text="emptyText"
      :expand-row-keys="expandRowKeys"
      :default-expand-all="defaultExpandAll"
      :default-sort="defaultSort"
      :tooltip-effect="tooltipEffect"
      :span-method="spanMethod"
      :select-on-indeterminate="selectOnIndeterminate"

      @sort-change="handleSortChange"
      @filter-change="handleFilterChange">
      <slot/>
      <slot name="append"/>
    </el-table>
    <div v-show="total>0" class="datatable-pagination-container">
      <el-pagination
        :current-page.sync="currentPage"
        :page-size.sync="pageSize"
        :page-sizes="pageSizes"
        :layout="layout"
        :total="total"
        background
        @size-change="handleSizeChange"
        @current-change="handleCurrentChange"/>
    </div>
  </div>
</template>

<script>
import waves from '@/directive/waves' // Waves directive
import request from '@/utils/request'
import { scrollTo } from '@/utils/scrollTo'

export default {
  name: 'DataTable',
  directives: { waves },
  props: {
    title: {
      type: String,
      default: null
    },
    showTitle: {
      type: Boolean,
      default: true
    },
    url: {
      type: String,
      default: null
    },
    params: {
      type: Object,
      default: null
    },
    layout: {
      type: String,
      default: 'total, sizes, prev, pager, next, jumper'
    },

    limit: {
      type: Number,
      default: 20
    },
    pageSizes: {
      type: Array,
      default() {
        return [10, 20, 30, 50]
      }
    },

    size: {
      type: String,
      default: 'small'
    },

    width: {
      type: [String, Number],
      default: undefined
    },

    height: {
      type: [String, Number],
      default: undefined
    },

    maxHeight: {
      type: [String, Number],
      default: undefined
    },

    fit: {
      type: Boolean,
      default: true
    },

    stripe: {
      type: Boolean,
      default: false
    },

    border: {
      type: Boolean,
      default: false
    },

    rowKey: {
      type: [String, Function],
      default: undefined
    },

    showHeader: {
      type: Boolean,
      default: true
    },

    showSummary: {
      type: Boolean,
      default: false
    },

    sumText: {
      type: [String],
      default: undefined
    },

    summaryMethod: {
      type: [Function],
      default: undefined
    },

    rowClassName: {
      type: [String, Function],
      default: undefined
    },

    rowStyle: {
      type: [Object, Function],
      default: undefined
    },

    cellClassName: {
      type: [String, Function],
      default: undefined
    },

    cellStyle: {
      type: [Object, Function],
      default: undefined
    },

    headerRowClassName: {
      type: [String, Function],
      default: undefined
    },

    headerRowStyle: {
      type: [Object, Function],
      default: undefined
    },

    headerCellClassName: {
      type: [String, Function],
      default: undefined
    },

    headerCellStyle: {
      type: [Object, Function],
      default: undefined
    },

    highlightCurrentRow: {
      type: Boolean,
      default: false
    },

    currentRowKey: {
      type: [String, Function],
      default: undefined
    },

    emptyText: {
      type: String,
      default: undefined
    },

    expandRowKeys: {
      type: Array,
      default: undefined
    },

    defaultExpandAll: {
      type: Boolean,
      default: false
    },

    defaultSort: {
      type: Object,
      default: undefined
    },

    tooltipEffect: {
      type: String,
      default: undefined
    },

    spanMethod: {
      type: Function,
      default: undefined
    },

    selectOnIndeterminate: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      start: 0,
      list: null,
      total: 0,
      listLoading: true,
      listQuery: {
        page: 1,
        limit: 20,
        query: null
      }
    }
  },
  computed: {
    currentPage: {
      get() {
        return this.listQuery.page
      },
      set(val) {
        this.listQuery.page = val
      }
    },
    pageSize: {
      get() {
        return this.listQuery.limit
      },
      set(val) {
        this.listQuery.limit = val
      }
    },
    showTitleWithText() {
      if (this.showTitle && !this.title) {
        return false
      } else {
        return true
      }
    },
    headerStyle() {
      if (this.border) {
        return {
          'border': '1px solid #ebeef5',
          'border-bottom': '0px solid #ebeef5'
        }
      } else {
        return {
          'border': '0px solid #ebeef5',
          'border-bottom': '1px solid #ebeef5'
        }
      }
    }
  },
  watch: {
    url() {
      this.getList()
    },
    params() {
      this.listQuery.page = 1
      this.getList()
    }
  },
  created() {
    this.getList()
  },
  mounted() {
  },
  methods: {

    handleSortChange(sortPms) {
      if ((sortPms != null) && (sortPms.prop != null) && (sortPms.order != null)) {
        var order = 'asc'
        if (sortPms.order === 'ascending') {
          order = 'asc'
        } else if (sortPms.order === 'descending') {
          order = 'desc'
        }
        this.listQuery.order = order
        this.listQuery.sort = sortPms.prop
        this.getList()
      } else {
        this.listQuery.order = null
        this.listQuery.sort = null
        this.getList()
      }
    },
    handleSizeChange(val) {
      this.scrollTop()
      this.getList()
    },
    handleCurrentChange(val) {
      this.scrollTop()
      this.getList()
    },
    scrollTop() {
      let obj = this.$el
      let offsetTop = 0
      while (obj) {
        offsetTop += obj.offsetTop
        obj = obj.offsetParent
      }
      const needScroll = window.scrollY - offsetTop > 0
      if (needScroll) {
        scrollTo(offsetTop, 800)
      }
    },

    getList() {
      this.listLoading = true
      const filters = []
      for (const i in this.filters) {
        if (this.filters[i].value && this.filters[i].value.length > 0) {
          filters.push({ 'field': this.filters[i].row, 'op': this.filters[i].op, 'value': this.filters[i].value })
        }
      }
      if (filters.length > 0) {
        this.listQuery.filters = JSON.stringify(filters)
      } else {
        this.listQuery.filters = null
      }
      const listQuery = Object.assign({}, this.listQuery)
      if (this.params) {
        for (const item in this.params) {
          listQuery[item] = this.params[item]
        }
      }
      request({
        url: this.url,
        method: 'get',
        params: listQuery
      }).then(response => {
        if (response.data instanceof Array) {
          this.list = response.data
        } else {
          this.list = response.data.rows
          this.total = response.data.total
        }

        this.listLoading = false
      })
    },

    handleFilterChange(filters) {
      let row = null
      let val = null
      for (const i in filters) {
        row = i
        val = filters[i]
      }
      const filter = [{
        row: row,
        op: 'contains',
        value: val
      }]
      this.setFilter(filter)
    },
    addData(data) {
      if (this.rowKey) {
        this.list.unshift(data)
      }
    },
    updateData(data) {
      if (this.rowKey) {
        for (const v of this.list) {
          if (v[this.rowKey] === data[this.rowKey]) {
            const index = this.list.indexOf(v)
            this.list.splice(index, 1, data)
            break
          }
        }
      }
    },

    deleteData(data) {
      if (this.rowKey) {
        const index = this.list.indexOf(data)
        this.list.splice(index, 1)
        this.total--
        if (this.list.length === 0) {
          if (this.total / this.listQuery.limit < this.listQuery.page) {
            this.listQuery.page--
          }
          this.getList()
        }
      }
    },

    setQuery(query) {
      this.listQuery.query = query
      this.getList()
    },
    setFilter(filters) {
      for (const i in filters) {
        let filter = null
        for (const j in this.filters) {
          if (filters[i]['row'] === this.filters[j]['row']) {
            filter = this.filters[j]
          }
        }
        if (filter == null) {
          this.filters.push({ 'row': filters[i].row, 'op': filters[i].op, 'value': filters[i].value })
        } else {
          filter.value = filters[i].value
          filter.op = filters[i].op
        }
      }

      this.listQuery.page = 1
      this.getList()
    }

  }
}
</script>

<style lang="scss" scoped>

.datatable-pagination-container.hidden {
  display: none;
}
.datatable-pagination-container {
    margin-top: 15px;
    margin-bottom: 15px;
}
  .datatable-header{
      height: 40px;
      width: 100%;
      background: white;
      padding: 12px 16px;
      /* border: 1px solid #ebeef5;
      border-bottom: 1px solid #ebeef5; */
      line-height: 1;
      .header-text{
        font-size: 18px;
        font-weight: bold;
        color:#303133;;
      }
  }
</style>

